Skip to content

release: v12.0.0 major release (approx. Q3 2026)#3280

Draft
kamilmysliwiec wants to merge 128 commits intomasterfrom
v12.0.0
Draft

release: v12.0.0 major release (approx. Q3 2026)#3280
kamilmysliwiec wants to merge 128 commits intomasterfrom
v12.0.0

Conversation

@kamilmysliwiec
Copy link
Copy Markdown
Member

@kamilmysliwiec kamilmysliwiec commented Mar 9, 2026

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe: v12.0.0 release

Description

Approximate release window: early Q3 2026

A brief list of changes:

  • nest new will now prompt users asking whether they want to use ESM or CJS for their project (ESM is the new default with vitest instead of jest)
  • the entire source code has been migrated to ESM
  • jest -> vitest for tests
  • e2e tests added for all commands
  • command classes have been refactored, and they now take context objects as inputs instead of non-types input and options arrays
  • webpack builder has been deprecated
  • rspack is the new default for monorepos
  • eslint to oxlint

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@kamilmysliwiec
Copy link
Copy Markdown
Member Author

A current version of this PR has been published under the next tag - @nestjs/cli@12.0.0-alpha.5

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prepares the Nest CLI v12 major release by migrating the codebase to ESM/NodeNext, switching the test runner from Jest to Vitest, and introducing rspack support (with webpack deprecated) alongside expanded e2e coverage.

Changes:

  • Add Vitest configuration (unit + e2e) and migrate existing unit tests from Jest to Vitest.
  • Migrate CLI/runtime code to ESM ("type": "module", .js import specifiers, NodeNext TS config) and refactor commands/actions to use typed context objects.
  • Add rspack compiler + defaults and add e2e tests across core CLI commands.

Reviewed changes

Copilot reviewed 128 out of 131 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
vitest.e2e.config.ts Adds Vitest config for e2e suite (timeouts, includes).
vitest.config.ts Adds Vitest config for unit tests and excludes e2e.
tsconfig.json Switches TS compilation to NodeNext/ES2022 and removes Jest types.
tools/postinstall.cjs Post-install helper for test fixtures + vitest timeout patching.
tools/clean.js Replaces gulp-based clean with a Node script to remove build artifacts.
test/lib/utils/get-default-tsconfig-path.spec.ts Migrates test from Jest to Vitest + ESM import specifiers.
test/lib/schematics/schematic.option.spec.ts Updates tests for boolean flag serialization changes + Vitest migration.
test/lib/schematics/nest.collection.spec.ts Migrates to Vitest and updates ESM import paths.
test/lib/schematics/custom.collection.spec.ts Migrates to Vitest and adds an ESM-safe mock for schematics tools.
test/lib/runners/schematic.runner.spec.ts Updates module-path resolution expectations for ESM.
test/lib/readers/file-system.reader.spec.ts Migrates to Vitest and updates reader imports.
test/lib/questions/questions.spec.ts Migrates to Vitest and updates ESM import paths/types usage.
test/lib/package-managers/yarn.package-manager.spec.ts Migrates to Vitest and updates ESM import paths/mocks.
test/lib/package-managers/pnpm.package-manager.spec.ts Migrates to Vitest and updates ESM import paths/mocks.
test/lib/package-managers/package-manager.factory.spec.ts Migrates to Vitest and updates typings for mock casting.
test/lib/package-managers/npm.package-manager.spec.ts Migrates to Vitest and updates ESM import paths/mocks.
test/lib/configuration/nest-configuration.loader.spec.ts Migrates to Vitest and updates ESM import paths.
test/lib/compiler/webpack/webpack-compiler.spec.ts Adds coverage for webpack compiler deprecation + ESM rejection behavior.
test/lib/compiler/swc/swc-compiler.spec.ts Updates SWC compiler unit tests for ESM module layout and Vitest mocks.
test/lib/compiler/rspack/rspack-defaults.spec.ts Adds tests for new rspack defaults factory (incl. ESM mode).
test/lib/compiler/rspack/rspack-compiler.spec.ts Adds unit tests for new rspack compiler behavior (watch, config merging).
test/lib/compiler/hooks/tsconfig-paths.hook.spec.ts Reworks hook tests to assert both CJS and ESM output (drops snapshots).
test/lib/compiler/hooks/fixtures/unused-imports/src/main.ts Updates fixture imports to include .js extension for ESM.
test/lib/compiler/hooks/fixtures/type-imports/src/main.ts Updates fixture relative imports to include .js extension for ESM.
test/lib/compiler/hooks/snapshots/tsconfig-paths.hook.spec.ts.snap Removes Jest snapshots now that assertions are explicit.
test/lib/compiler/helpers/get-value-or-default.spec.ts Migrates helper test to Vitest and ESM import specifiers.
test/lib/compiler/helpers/get-rspack-config-path.spec.ts Adds tests for new rspack config-path helper.
test/jest-config.json Removes Jest test configuration.
test/e2e/new.command.e2e-spec.ts Adds e2e coverage for nest new behaviors (language, strict, flags).
test/e2e/jest-e2e.json Adds fixture Jest config used by generated projects in e2e scenarios.
test/e2e/info.command.e2e-spec.ts Adds e2e coverage for nest info with/without deps installed.
test/e2e/helpers.ts Adds shared e2e utilities for running/spawning CLI and scaffolding projects.
test/e2e/generate.command.e2e-spec.ts Adds e2e coverage for nest generate across many schematic types/flags.
test/e2e/build.command.e2e-spec.ts Adds e2e coverage for nest build (tsc/swc + monorepo webpack cases).
test/e2e/add.command.e2e-spec.ts Adds e2e coverage for nest add (install + dry-run/skip-install).
test/actions/info.action.spec.ts Migrates action tests to Vitest and adapts to private method access.
test/actions/build.action.spec.ts Adds unit tests for builder dispatch behavior (webpack vs rspack).
package.json Marks package as ESM, switches to Vitest scripts, updates deps/peers, replaces clean step.
lib/utils/tree-kill.ts Renames internals to clearer “children” naming.
lib/utils/remaining-flags.ts Updates commander integration to use Command + getOptionValue().
lib/utils/project-utils.ts Removes hasValidOptionFlag and updates imports for ESM layout.
lib/utils/local-binaries.ts Converts local command loader to async ESM import of local CLI commands.
lib/utils/load-configuration.ts Updates imports for ESM layout.
lib/utils/is-module-available.ts Uses createRequire for ESM-safe module resolution.
lib/utils/is-esm-project.ts Adds helper to detect ESM projects via package.json "type": "module".
lib/ui/messages.ts Updates ESM import specifier for emojis module.
lib/ui/index.ts Updates barrel exports to explicit .js specifiers.
lib/schematics/schematic.option.ts Changes boolean option rendering to --flag=false for false.
lib/schematics/nest.collection.ts Updates imports for ESM layout.
lib/schematics/index.ts Updates barrel exports to explicit .js specifiers.
lib/schematics/custom.collection.ts Updates NodeWorkflow import to explicit /index.js for ESM.
lib/schematics/collection.factory.ts Updates imports for ESM layout.
lib/schematics/abstract.collection.ts Updates imports for ESM layout.
lib/runners/yarn.runner.ts Updates import specifier for ESM layout.
lib/runners/schematic.runner.ts Reworks module-path resolution to be ESM-safe via createRequire.
lib/runners/runner.factory.ts Changes unsupported runner behavior from warn+continue to throwing an Error.
lib/runners/pnpm.runner.ts Updates import specifier for ESM layout.
lib/runners/npm.runner.ts Updates import specifier for ESM layout.
lib/runners/index.ts Updates barrel exports to explicit .js specifiers.
lib/runners/git.runner.ts Updates import specifier for ESM layout.
lib/runners/abstract.runner.ts Updates UI import for ESM layout and aligns variable naming with lint config.
lib/readers/index.ts Updates barrel exports to explicit .js specifiers.
lib/readers/file-system.reader.ts Updates reader import specifier for ESM layout.
lib/questions/questions.ts Removes any return annotation from generateInput factory.
lib/package-managers/yarn.package-manager.ts Updates imports for ESM layout.
lib/package-managers/pnpm.package-manager.ts Updates imports for ESM layout.
lib/package-managers/package-manager.factory.ts Updates imports for ESM layout and simplifies catch handling.
lib/package-managers/npm.package-manager.ts Updates imports for ESM layout.
lib/package-managers/index.ts Updates barrel exports to explicit .js specifiers.
lib/package-managers/abstract.package-manager.ts Migrates to fs/promises, ESM ora import, and tightens typing for package.json reads.
lib/configuration/nest-configuration.loader.ts Updates imports, fixes a typo in comment, and simplifies defaulting logic.
lib/configuration/index.ts Updates barrel exports to explicit .js specifiers.
lib/configuration/defaults.ts Updates imports and adds default rspack config filename constant.
lib/configuration/configuration.ts Extends builder types to include rspack and tightens several type definitions.
lib/configuration/configuration.loader.ts Updates import specifier for ESM layout.
lib/compiler/webpack-compiler.ts Adds webpack deprecation messaging, ESM project guard, and lazy-loads webpack deps.
lib/compiler/watch-compiler.ts Updates imports for ESM layout.
lib/compiler/typescript-loader.ts Reworks TS binary resolution for ESM (no module.paths reliance).
lib/compiler/swc/type-checker-host.ts Updates imports and logs type-check errors to stderr.
lib/compiler/swc/swc-compiler.ts ESM migration (createRequire/dirname), better error handling, and safer deep-merge own-property checks.
lib/compiler/swc/forked-type-checker.ts Updates imports and sends errors to stderr.
lib/compiler/swc/constants.ts Removes unused constant.
lib/compiler/rspack-compiler.ts Introduces new Rspack compiler implementation with watch/build flows.
lib/compiler/plugins/plugins-loader.ts ESM-safe plugin resolution via createRequire, fixes PluginAndOptions typing, improves error causes.
lib/compiler/plugins/plugin-metadata-printer.ts Updates import specifier for ESM layout.
lib/compiler/plugins/plugin-metadata-generator.ts Updates imports for ESM layout.
lib/compiler/hooks/tsconfig-paths.hook.ts ESM-safe resolution updates and removes os.platform() dependency.
lib/compiler/helpers/tsconfig-provider.ts Updates imports for ESM layout.
lib/compiler/helpers/get-webpack-config-path.ts Updates signature to accept option records instead of Input[] arrays.
lib/compiler/helpers/get-value-or-default.ts Changes option handling from Input[] to Record-based access for context objects.
lib/compiler/helpers/get-tsc-config.path.ts Updates signature to accept option records instead of Input[] arrays.
lib/compiler/helpers/get-rspack-config-path.ts Adds helper for rspack config path resolution from builder config.
lib/compiler/helpers/get-builder.ts Updates signature to accept option records instead of Input[] arrays.
lib/compiler/helpers/delete-out-dir.ts Updates imports for ESM layout.
lib/compiler/defaults/webpack-defaults.ts Lazy-loads webpack-related deps and improves missing-dep errors for optional installation.
lib/compiler/defaults/swc-defaults.ts Updates imports for ESM layout.
lib/compiler/defaults/rspack-defaults.ts Adds rspack defaults factory with ESM/CJS support and optional plugin integration.
lib/compiler/compiler.ts Updates imports and tightens extra arg typing.
lib/compiler/base-compiler.ts Refines abstract method return types and restricts some methods to protected.
lib/compiler/assets-manager.ts Updates imports and improves error message typing with cause.
gulpfile.js Removes legacy gulp entrypoint for cleaning/build tooling.
eslint.config.js Adds new flat-config ESLint setup for TS/ESM repo layout.
commands/start.command.ts Migrates to context-based action invocation and updates commander types.
commands/new.command.ts Migrates to context-based action invocation and updates language normalization logic.
commands/info.command.ts Updates commander types and ESM imports.
commands/index.ts Updates exports and adds context exports.
commands/generate.command.ts Migrates to context-based invocation and updates --spec option default semantics.
commands/context/start.context.ts Adds typed context interface for start command.
commands/context/new.context.ts Adds typed context interface for new command.
commands/context/index.ts Adds context barrel exports.
commands/context/generate.context.ts Adds typed context interface for generate command.
commands/context/build.context.ts Adds typed context interface for build command.
commands/context/add.context.ts Adds typed context interface for add command.
commands/command.loader.ts Adds ESM compatibility guard for global/local CLI mismatches and improves invalid command handling.
commands/build.command.ts Migrates to context-based action invocation and adds rspack to builder help text.
commands/add.command.ts Migrates to context-based action invocation and passes through remaining flags.
commands/abstract.command.ts Updates commander type usage for ESM migration.
bin/nest.ts Switches to new Command() for ESM, marks program as ESM-compatible, awaits local loader import.
actions/start.action.ts Refactors to accept StartCommandContext and adapts runBuild/start lifecycle to ESM.
actions/new.action.ts Refactors to accept NewCommandContext and updates prompting + schematic option mapping.
actions/info.action.ts Refactors internal methods to private, uses padEnd, and updates ESM imports.
actions/index.ts Updates exports to explicit .js specifiers.
actions/generate.action.ts Refactors to accept GenerateCommandContext and updates schematic-option mapping.
actions/build.action.ts Refactors to context-based inputs, adds rspack builder support, and updates ESM imports/dynamic imports.
actions/add.action.ts Refactors to AddCommandContext and removes reliance on Input[] option scanning.
actions/abstract.action.ts Simplifies AbstractAction API to a single context parameter.
.eslintrc.js Removes legacy ESLint RC config in favor of flat config.
.eslintignore Removes legacy ignore file (handled in flat config).
.circleci/config.yml Updates CI to run Vitest and adds separate e2e job.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/package-managers/abstract.package-manager.ts
Comment thread lib/compiler/helpers/get-rspack-config-path.ts
Comment thread tools/clean.js Outdated
Comment thread tools/postinstall.cjs Outdated
Comment thread tools/postinstall.cjs
Comment thread test/lib/readers/file-system.reader.spec.ts
Comment thread test/e2e/build.command.e2e-spec.ts
Comment thread test/e2e/build.command.e2e-spec.ts
Copy link
Copy Markdown

Copilot AI commented Mar 11, 2026

@kamilmysliwiec I've opened a new pull request, #3282, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown

Copilot AI commented Mar 11, 2026

@kamilmysliwiec I've opened a new pull request, #3283, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown

Copilot AI commented Mar 11, 2026

@kamilmysliwiec I've opened a new pull request, #3284, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown

Copilot AI commented Mar 11, 2026

@kamilmysliwiec I've opened a new pull request, #3285, to work on those changes. Once the pull request is ready, I'll request review from you.

maruthang and others added 30 commits April 15, 2026 15:36
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per review on #3340: a single file-system event can trigger many 'add' or
'change' callbacks in quick succession (e.g., a git checkout or a bulk
editor save), which would previously cause one restart per event.

Wrap onSuccess in a 150ms trailing debouncer so bursts of events collapse
into a single restart. 150ms is below human-perceivable latency but large
enough to coalesce filesystem event storms on all tested platforms.
Verifies both the positive path (flag emits .d.ts files alongside .js)
and the negative path (default SWC build does not emit declarations).
The scaffolded app's node_modules contains the published @nestjs/cli,
which bin/nest.js delegates to via localBinExists(). The new
--emit-declarations flag doesn't exist there yet, so the test fails
with 'unknown option'. removeLocalCli() forces the dev CLI to run.
The SWC compiler delegates declaration emission to 'tsc --emitDeclarationOnly',
which silently produces no output when declaration: false. The default
NestJS scaffold sets declaration: false in tsconfig.build.json, so enable
it in the test via a targeted write (restored in a finally block so
subsequent tests aren't affected).
…ailure

Previous test asserted specific .d.ts paths. When those assertions failed
on CI, there was no signal about where the files actually landed (or
whether tsc silently emitted none). Replace with a recursive walk of dist/
plus diagnostic logging of nest build output and dist contents, so the
next failing run tells us exactly what happened.

Also enable declaration: true in tsconfig.json (not just tsconfig.build.json)
in case nest resolves the root tsconfig when invoking tsc --emitDeclarationOnly.
…set-change

feat(assets): restart app on asset change in watch mode (#2626)
feat(swc): add emit declarations flag for type definition generation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The scaffoldMonorepoWithDeps helper uses a naive capitalize-first-letter
transform that produces invalid TypeScript identifiers like `My-libModule`
when the sub-app name contains a hyphen. Renaming the test's sub-app from
`my-lib` to `mylib` sidesteps the issue without changing the helper.
Two CI failures were masking each other:

1. scaffoldMonorepoWithDeps scaffolds an ESM project (since `nest new`
   defaults to type: module in v12), but the manually-written sub-app
   source files use CJS-style imports without .js extensions. With
   moduleResolution: NodeNext this fails with TS2307 'Cannot find module
   ./mylib.module'. Calling convertToCjs() aligns the project format.

2. includeLibraryAssets is introduced by this PR and absent from the
   published @nestjs/cli that the scaffolded project installs, so
   bin/nest.js delegates to a CLI that ignores the option. removeLocalCli
   forces the dev CLI to be used.
With tsconfig include: ['src/**/*'], tsc infers rootDir as src/, so the
compiled main.js sits directly at dist/apps/<name>/main.js — not under
a src/ subdir. Matches the path assertion used by the existing webpack
monorepo test in build.command.e2e-spec.ts.
…ests

Existing closeWatchers and onSuccess tests need an additional
mockReturnValueOnce([]) entry to account for the new
includeLibraryAssets getValueOrDefault call introduced by this PR.
Without it, the mock chain shifts and tests fail with TypeError when
sourceRoot resolves to a non-string.
Add an opt-in --format flag to nest generate and nest new commands.
When passed, the format option is propagated to the schematic so it
can format generated files (e.g. with Prettier) before writing them
to disk. The default is off, so no existing project behavior changes
unless the flag is explicitly enabled.

This is the CLI-side change. The actual formatting logic lives in
@nestjs/schematics.

Closes #316
Exercises two paths through the format option wiring:
- nest generate controller <name> --no-format -> format=false is
  accepted and the controller is still generated.
- nest generate controller <name> (flag omitted) -> format
  defaults to true and the controller is generated.

The tests do not assert that prettier formatting has actually been
applied because the companion @nestjs/schematics change lives on a
separate major release line; here we only want to guarantee the CLI
parses the flag and passes it through without regressing other
generate paths.
feat(generate): pass format option to schematics
The `getRspackConfigPath` helper already honours `cmdOptions.rspackPath`
and its unit tests cover the CLI-path precedence case, but neither the
`build` nor the `start` command wires the flag through from commander.
As a result, projects using the rspack builder could only point at a
custom rspack config via `nest-cli.json`, with no equivalent of the
existing `--webpackPath` CLI option.

Mirror the existing `--webpackPath` pattern:

- register `--rspackPath [path]` on both `build` and `start` commands
- forward `options.rspackPath` into the respective command contexts
- extend the `BuildCommandContext` / `StartCommandContext` interfaces

Also adds a unit test confirming the option flows from the build action
into `getRspackConfigPath`.
`retrieveCols` (used to center-pad the post-install banner printed after
`nest new`) only asked the shell for the terminal width via `tput cols`.
On Windows, `tput` is not installed by default, so the call always threw
and the function silently fell back to the hard-coded 80 columns — even
for users with wider terminals. The same fallback also kicks in whenever
`tput` is missing from a sandboxed or minimal Linux image.

Ask Node first: `process.stdout.columns` is maintained by the runtime on
every platform and reflects the actual terminal width (or `undefined` /
`0` when stdout is not a TTY). When it is a positive number, use it
directly and skip the `execSync` call entirely — this removes a small
per-invocation process spawn as well. Keep the existing `tput cols`
path and the 80-column default as secondary/tertiary fallbacks for the
non-TTY case.

Also adds unit tests covering the three branches (stdout.columns set,
tput fallback, and the final default).
Backports the master-branch fix for #3229 (PR #3275) to v12.0.0. The
`@nestjs/schematics` resource generator defines `--type` and `--crud`
options in its schema.json, but the v12 CLI does not register either
flag on the `generate` command. Running:

    nest g resource users --type rest --crud

exits with "error: unknown option '--type'" even though the schematic
itself would handle both flags correctly.

- register `--type [type]` and `--crud` on the generate command
- forward both into the generate action and on to the schematic
- only forward `--crud` when explicitly passed (avoid toggling default
  behavior on users who never opted in)

The master-branch PR noted that "no automated tests were added because
there are no existing e2e tests for generate resource" — this PR adds a
focused unit spec for `GenerateAction` covering forwarding of the new
options individually and together.
feat(generate): accept type and crud options on the resource schematic
fix(new): prefer process.stdout.columns over tput for terminal width
feat(cli): add rspack config path option to build and start commands
…aries

feat(assets): add option to include library assets in app builds
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants